﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
using System.Xml.Serialization;

namespace SpaceshipDuelConfig
{
    /// <summary>
    /// Struktur für Bildschirmauflösung
    /// </summary>
    struct Resolution
    {
        public Resolution(int newWidth, int newHeight, string newName)
        {
            width = newWidth;
            height = newHeight;
            name = newName;
        }

        public int width;   // Breite in Pixel
        public int height;  // Höhe in Pixel
        public string name; // Name im Format "BreitexHöhe"
    }

    /// <summary>
    /// Form-Klasse
    /// </summary>
    public partial class FormMain : Form
    {
        #region Private fields

        List<Resolution> resolutions;
        ConfigData confData;

        #endregion Private fields

        #region Construction

        /// <summary>
        /// Standard-Konstruktor
        /// </summary>
        public FormMain()
        {
            resolutions = new List<Resolution>();
            confData = new ConfigData(-1, -1, true, 0, "W", "S", "A", "D", "Q", "E", "I", "K", "J", "L", "U", "O");
            InitializeComponent();
        }

        #endregion Construction

        #region Private methods

        /// <summary>
        /// Shown-Methode der Form
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FormMain_Shown(object sender, EventArgs e)
        {
            // Liste der auswählbaren Auflösungen anlegen
            resolutions.Add(new Resolution(-1, -1, "automatisch"));
            resolutions.Add(new Resolution(800, 600, "800x600"));
            resolutions.Add(new Resolution(1024, 768, "1024x768"));
            resolutions.Add(new Resolution(1280, 720, "1280x720"));
            resolutions.Add(new Resolution(1280, 800, "1280x800"));
            resolutions.Add(new Resolution(1280, 960, "1280x960"));
            resolutions.Add(new Resolution(1400, 1050, "1400x1050"));
            resolutions.Add(new Resolution(1440, 900, "1440x900"));
            resolutions.Add(new Resolution(1600, 900, "1600x900"));
            resolutions.Add(new Resolution(1600, 1200, "1600x1200"));
            resolutions.Add(new Resolution(1680, 1050, "1680x1050"));
            resolutions.Add(new Resolution(1920, 1080, "1920x1080"));
            resolutions.Add(new Resolution(1920, 1200, "1920x1200"));
            resolutions.Add(new Resolution(1920, 1440, "1920x1440"));

            for (int i=0; i<resolutions.Count; i++)
                comboBoxResolution.Items.Add(resolutions[i].name);

            comboBoxResolution.SelectedIndex = 0;

            ReadConfig();
        }

        /// <summary>
        /// Einlesen der Konfiguration, Darstellung der gespeicherten Parameter
        /// </summary>
        private void ReadConfig()
        {
            try
            {
                confData = DeserializeFromXml();

                if (confData.FullscreenMode == true)
                    radioButtonFullscreenMode.Checked = true;
                else
                    radioButtonWindowMode.Checked = true;

                string resName = confData.ResolutionWidth.ToString() + "x" + confData.ResolutionHeight.ToString();

                if (comboBoxResolution.Items.Contains(resName) == true)
                    comboBoxResolution.SelectedIndex = comboBoxResolution.Items.IndexOf(resName);
                else
                    comboBoxResolution.SelectedIndex = 0;

                if (confData.Volume >= 0 && confData.Volume <= 100)
                    trackBarVolume.Value = confData.Volume;
                else
                    trackBarVolume.Value = 100;

                if (cbPlayer1Up.Items.Contains(confData.Player1KeyUp) == true)
                    cbPlayer1Up.SelectedIndex = cbPlayer1Up.Items.IndexOf(confData.Player1KeyUp);
                else
                    cbPlayer1Up.SelectedIndex = 0;

                if (cbPlayer1Down.Items.Contains(confData.Player1KeyDown) == true)
                    cbPlayer1Down.SelectedIndex = cbPlayer1Down.Items.IndexOf(confData.Player1KeyDown);
                else
                    cbPlayer1Down.SelectedIndex = 0;

                if (cbPlayer1Left.Items.Contains(confData.Player1KeyLeft) == true)
                    cbPlayer1Left.SelectedIndex = cbPlayer1Left.Items.IndexOf(confData.Player1KeyLeft);
                else
                    cbPlayer1Left.SelectedIndex = 0;

                if (cbPlayer1Right.Items.Contains(confData.Player1KeyRight) == true)
                    cbPlayer1Right.SelectedIndex = cbPlayer1Right.Items.IndexOf(confData.Player1KeyRight);
                else
                    cbPlayer1Right.SelectedIndex = 0;

                if (cbPlayer1Fire.Items.Contains(confData.Player1KeyFire) == true)
                    cbPlayer1Fire.SelectedIndex = cbPlayer1Fire.Items.IndexOf(confData.Player1KeyFire);
                else
                    cbPlayer1Fire.SelectedIndex = 0;

                if (cbPlayer1Special.Items.Contains(confData.Player1KeySpecial) == true)
                    cbPlayer1Special.SelectedIndex = cbPlayer1Special.Items.IndexOf(confData.Player1KeySpecial);
                else
                    cbPlayer1Special.SelectedIndex = 0;

                if (cbPlayer2Up.Items.Contains(confData.Player2KeyUp) == true)
                    cbPlayer2Up.SelectedIndex = cbPlayer2Up.Items.IndexOf(confData.Player2KeyUp);
                else
                    cbPlayer2Up.SelectedIndex = 0;

                if (cbPlayer2Down.Items.Contains(confData.Player2KeyDown) == true)
                    cbPlayer2Down.SelectedIndex = cbPlayer2Down.Items.IndexOf(confData.Player2KeyDown);
                else
                    cbPlayer2Down.SelectedIndex = 0;

                if (cbPlayer2Left.Items.Contains(confData.Player2KeyLeft) == true)
                    cbPlayer2Left.SelectedIndex = cbPlayer2Left.Items.IndexOf(confData.Player2KeyLeft);
                else
                    cbPlayer2Left.SelectedIndex = 0;

                if (cbPlayer2Right.Items.Contains(confData.Player2KeyRight) == true)
                    cbPlayer2Right.SelectedIndex = cbPlayer2Right.Items.IndexOf(confData.Player2KeyRight);
                else
                    cbPlayer2Right.SelectedIndex = 0;

                if (cbPlayer2Fire.Items.Contains(confData.Player2KeyFire) == true)
                    cbPlayer2Fire.SelectedIndex = cbPlayer2Fire.Items.IndexOf(confData.Player2KeyFire);
                else
                    cbPlayer2Fire.SelectedIndex = 0;

                if (cbPlayer2Special.Items.Contains(confData.Player2KeySpecial) == true)
                    cbPlayer2Special.SelectedIndex = cbPlayer2Special.Items.IndexOf(confData.Player2KeySpecial);
                else
                    cbPlayer2Special.SelectedIndex = 0;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Fehler beim Einlesen der Konfigurationsdatei: " + ex.Message);
            }
        }

        /// <summary>
        /// Speichern-Button wurde gedrückt
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonSaveConfig_Click(object sender, EventArgs e)
        {
            DisableGUI(true);
            confData.FullscreenMode = radioButtonFullscreenMode.Checked;
            confData.ResolutionWidth = resolutions[comboBoxResolution.SelectedIndex].width;
            confData.ResolutionHeight = resolutions[comboBoxResolution.SelectedIndex].height;
            confData.Volume = trackBarVolume.Value;
            confData.Player1KeyDown     = cbPlayer1Down.Items[cbPlayer1Down.SelectedIndex].ToString();
            confData.Player1KeyFire     = cbPlayer1Fire.Items[cbPlayer1Fire.SelectedIndex].ToString();
            confData.Player1KeyLeft     = cbPlayer1Left.Items[cbPlayer1Left.SelectedIndex].ToString();
            confData.Player1KeyRight    = cbPlayer1Right.Items[cbPlayer1Right.SelectedIndex].ToString();
            confData.Player1KeySpecial  = cbPlayer1Special.Items[cbPlayer1Special.SelectedIndex].ToString();
            confData.Player1KeyUp       = cbPlayer1Up.Items[cbPlayer1Up.SelectedIndex].ToString();
            confData.Player2KeyDown     = cbPlayer2Down.Items[cbPlayer2Down.SelectedIndex].ToString();
            confData.Player2KeyFire     = cbPlayer2Fire.Items[cbPlayer2Fire.SelectedIndex].ToString();
            confData.Player2KeyLeft     = cbPlayer2Left.Items[cbPlayer2Left.SelectedIndex].ToString();
            confData.Player2KeyRight    = cbPlayer2Right.Items[cbPlayer2Right.SelectedIndex].ToString();
            confData.Player2KeySpecial  = cbPlayer2Special.Items[cbPlayer2Special.SelectedIndex].ToString();
            confData.Player2KeyUp       = cbPlayer2Up.Items[cbPlayer2Up.SelectedIndex].ToString();
            SerializeToXML(confData);
            DisableGUI(false);
        }

        /// <summary>
        /// Serialisierung in XML-Datei (Speichern)
        /// </summary>
        /// <param name="dataObj"></param>
        private void SerializeToXML(ConfigData dataObj)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(ConfigData));
            FileStream file = new FileStream(Application.StartupPath + "\\config.xml", FileMode.Create);
            serializer.Serialize(file, dataObj);
            file.Close();
        }

        /// <summary>
        /// Deserialisierung aus XML-Datei (Laden)
        /// </summary>
        /// <returns></returns>
        private ConfigData DeserializeFromXml()
        {
            XmlSerializer serializer = new XmlSerializer(typeof(ConfigData));
            FileStream file = new FileStream(Application.StartupPath + "\\config.xml", FileMode.Open);
            ConfigData myData = serializer.Deserialize(file) as ConfigData;
            file.Close();
            return myData;
        }

        /// <summary>
        /// GUI-Elemente sperren/entsperren
        /// </summary>
        /// <param name="disable"></param>
        private void DisableGUI(bool disable)
        {
            buttonSaveConfig.Enabled            = !disable;
            buttonStartGame.Enabled             = !disable;
            comboBoxResolution.Enabled          = !disable;
            radioButtonFullscreenMode.Enabled   = !disable;
            radioButtonWindowMode.Enabled       = !disable;
        }

        /// <summary>
        /// Änderung des Volumewertes mittels Trackbar
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void trackBarVolume_ValueChanged(object sender, EventArgs e)
        {
            labelVolume.Text = string.Format("{0}%", trackBarVolume.Value);
        }

        
        /// <summary>
        /// Startet die exe des Spiels
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonStartGame_Click(object sender, EventArgs e)
        {
            buttonSaveConfig_Click(sender, null);
            Process.Start("spaceshipduel.exe");
            Close();
        }

        #endregion Private methods
    }
}
